
#include "StarSelect.h"

#include <set>
#include <QString>

#include <libnova.h>
#include <indicom.h>

void StarSelect::setSite(double lng, double lat)
{
  this->lng=lng;
  this->lat=lat;
}

void StarSelect::setLST(double lst)
{
  this->lst = lst;
}

void StarSelect::setCatalog(Catalog* cat)
{
  this->catalog=cat;
}

void StarSelect::actualizeAltAz(double nlst)
{
  unsigned int magcount=0;
  if (nlst != 0.0) this->lst = nlst;
  actualizelst=lst;
  if (visibleStars.empty()) {

   for (std::vector<StarEntry *>::iterator it=catalog->getStars()->begin(); it != catalog->getStars()->end(); ++it) {
     StarEntry *se=*it;
     struct ln_hrz_posn altaz;
     struct ln_equ_posn radec, propermotion, radecnow;
     double jd = ln_get_julian_from_sys(); // use UTC from pad
     struct ln_lnlat_posn obs;
     star *newstar;
     //printf("Processing star %s\n", se->name.toAscii().data());
     radec.ra = (se->raJ2000 * 360.0) / 24.0; radec.dec=se->decJ2000; 
     propermotion.ra = se->pmRA; propermotion.dec=se->pmDE;
     //ln_get_equ_prec(&radec, jd, &radecnow);
     ln_get_apparent_posn(&radec, &propermotion, jd, &radecnow);
     obs.lng = lng; obs.lat=lat;
     ln_get_hrz_from_equ(&radec, &obs, jd, &altaz); // should use jd derived from utc time
     altaz.az += 180.0; if (altaz.az >= 360.0) altaz.az -= 360.0;
     newstar=new star((*it), altaz.alt, altaz.az, (radecnow.ra * 24.0) / 360.0, radecnow.dec);
     if (altaz.alt > 0.0) {
      visibleStars.insert(newstar);
     }
     if ((altaz.alt > 0.0) && ((*it)->vmag <= MAG_LIMIT)) {
       magcount += 1;
     }
     if ((altaz.alt >= MIN_NORTH_ALT) && (altaz.alt <= MAX_NORTH_ALT) && (altaz.az >=0.0) && (altaz.az <= MAX_AZ) 
	&& ((*it)->vmag <= MAG_LIMIT))
       alignNEStars.insert(newstar);
     if ((altaz.alt >= MIN_NORTH_ALT) && (altaz.alt <= MAX_NORTH_ALT) && (altaz.az <360.0) && (altaz.az >= (360.0-MAX_AZ)) 
	&& ((*it)->vmag <= MAG_LIMIT))
       alignNWStars.insert(newstar);
      if ((altaz.alt >= MIN_SOUTH_ALT) && (altaz.alt <= MAX_SOUTH_ALT) && (altaz.az < 180.0) && (altaz.az >= (180.0 -MAX_AZ)) 
	&& ((*it)->vmag <= MAG_LIMIT))
       alignSEStars.insert(newstar);
     if ((altaz.alt >= MIN_SOUTH_ALT) && (altaz.alt <= MAX_SOUTH_ALT) && (altaz.az >=180.0) && (altaz.az <= (180.0+MAX_AZ)) 
	&& ((*it)->vmag <= MAG_LIMIT))
       alignSWStars.insert(newstar);      
   }
  }
  printf("Stars %d visible (%d < mag %g), %d NE, %d NW, %d SE, %d SW\n",visibleStars.size(), magcount, MAG_LIMIT, 
	 alignNEStars.size(), alignNWStars.size(),
	 alignSEStars.size(), alignSWStars.size());
}

void StarSelect::computePairs()
{
  alignPairs.clear();
  std::set<star *, starmag>::iterator it1, it2;
  for ( it1=alignSWStars.begin(); it1 != alignSWStars.end(); ++it1) {
    for (it2=alignNWStars.begin(); it2 != alignNWStars.end(); ++it2) {
       alignPairs.insert(alignPairs.end(), std::make_pair<star *, star*>(*it1, *it2));
    }
  }
  for (it1=alignSEStars.begin(); it1 != alignSEStars.end(); ++it1) {
    for (it2=alignNEStars.begin(); it2 != alignNEStars.end(); ++it2) {
       alignPairs.insert(alignPairs.end(), std::make_pair<star *, star*>(*it1, *it2));
    }
  }  
  
  // Sort by vmag1 + vmag2
  std::sort(alignPairs.begin(), alignPairs.end(), sortstarpair);
  
  emit layoutChanged();
}

StarSelect::alignpair StarSelect::getPair(QModelIndex index)
{
  //printf("Retrieving star pair %d\n", index.row());
  return alignPairs.at(index.row());
}


int StarSelect::rowCount(const QModelIndex& parent) const
{
  //printf("Row count %d\n", stars.size());
  return alignPairs.size();
}

int StarSelect::columnCount(const QModelIndex& parent) const
{
  //printf("Column count\n");
  return 7;
}

QVariant StarSelect::data(const QModelIndex& index, int role) const
{ 
  //printf("data %d %d %d %g\n", role, index.row(), index.column(), stars.at(index.row())->raJ2000);
  if(role == Qt::DisplayRole)
    {
      char ra[9], de[9];
      char salt[11], saz[11];
      //printf("data %d %d %d %g\n", role, index.row(), index.column(), stars.at(index.row())->raJ2000);
      switch (index.column()) {
	case 0: return QString(SIDE(alignPairs.at(index.row()).first->az));
	//case 1: fs_sexa(ra, alignPairs.at(index.row()).first->starentry->raJNOW, 2, 3600);
	//        fs_sexa(de, alignPairs.at(index.row()).first->starentry->decJNOW, 2, 3600);
	//	return QString(ra) + QString(" - ") + QString(de);
	case 1: fs_sexa(salt, alignPairs.at(index.row()).first->alt, 3, 3600);
	        fs_sexa(saz, alignPairs.at(index.row()).first->az, 3, 3600);
		return QString(salt) + QString(" - ") + QString(saz);

	case 2: return QString::number(alignPairs.at(index.row()).first->starentry->vmag);
	case 3: return alignPairs.at(index.row()).first->starentry->name;
	//case 4: fs_sexa(ra, alignPairs.at(index.row()).second->starentry->raJNOW, 2, 3600);
	//        fs_sexa(de, alignPairs.at(index.row()).second->starentry->decJNOW, 2, 3600);
	//	return QString(ra) + QString(" - ") + QString(de);
	case 4: fs_sexa(salt, alignPairs.at(index.row()).second->alt, 3, 3600);
	        fs_sexa(saz, alignPairs.at(index.row()).second->az, 3, 3600);
		return QString(salt) + QString(" - ") + QString(saz);
		
	case 5: return QString::number(alignPairs.at(index.row()).second->starentry->vmag);
	case 6: return alignPairs.at(index.row()).second->starentry->name;
    }
  }
  return QVariant::Invalid;
}

QVariant StarSelect::headerData(int section, Qt::Orientation orientation, int role) const
{
  //printf("headerData\n");
  if(role == Qt::DisplayRole)
  {
    if(orientation == Qt::Horizontal)
      switch (section) {
	case 0: return QString("");
	case 1: return QString("Star 1 (alt/az)");
	case 2: return QString("mag");
	case 3: return QString("Name");
	case 4: return QString("Star 2 (alt/az)");
	case 5: return QString("mag");
	case 6: return QString("Name");
    }
    }
  return QVariant::Invalid;
}

